#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <lua.h>
#include "win32_basic_ui.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

const char g_szClassName[] = "myWindowClass";

long WINAPI Thread()
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    HINSTANCE hInstance = GetModuleHandle(NULL);

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "Lua Script Console",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

int ThreadTest()
{
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, 0,0,0);
    return 0;
}

int ChooseProject(lua_State *L)
{
    // http://msdn.microsoft.com/en-us/library/ms646839(VS.85).aspx
    OPENFILENAME file;
    memset(&file, 0, sizeof(OPENFILENAME));
    file.lStructSize = sizeof(OPENFILENAME);
    file.hwndOwner = NULL;
    file.lpstrFilter = "Guacamole Project file (*.project.lua)\0*.project.lua\0All Files (*.*)\0*.*\0";
    file.lpstrTitle = "Please select a Guacamole Project file to open.";
    file.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;

    char FileName[1024] = "";
    file.lpstrFile = FileName;
    file.nMaxFile = 1024;

    if (!GetOpenFileName(&file))
        lua_pushnil(L);
    else
        lua_pushstring(L, FileName);

    return 1;
}

int ShowError(lua_State *L)
{
    lua_Debug dbg;
    int i = 0;
    while (lua_getstack(L, i, &dbg))
    {
        lua_pushfstring(L, "\r\n[Line %d] %s", dbg.currentline, dbg.name);
        i++;
    }
    lua_concat(L,i + 1);
    MessageBox(NULL, lua_tostring(L,-1), "Error", MB_OK | MB_ICONSTOP);
    return 0;
}

int ShowWarning(lua_State *L)
{
    MessageBox(NULL, lua_tostring(L,-1), "Warning", MB_OK | MB_ICONEXCLAMATION);
    return 0;
}

int ShowInfo(lua_State *L)
{
    MessageBox(NULL, lua_tostring(L,-1), "Info", MB_OK | MB_ICONINFORMATION);
    return 0;
}

int UpdateAppPath(lua_State *L)
{
    char FileName[1024] = "";
    GetModuleFileName(NULL, FileName, 1024);
    lua_pop(L,1);
    lua_pushstring(L, FileName);
    return 0;
}

// http://www.codeguru.com/cpp/w-p/win32/tutorials/print.php/c12873
int SetIcon(lua_State *L)
{
    HANDLE hWhere = BeginUpdateResource(lua_tostring(L,1), FALSE);

    size_t buffersize;

    const char* buffer = lua_tolstring(L,2,&buffersize);

    UpdateResource(
        hWhere,                     // handle to the executable
        RT_ICON,                    // Resource type - icon
        MAKEINTRESOURCE(1),         // Make the id 1
        MAKELANGID(LANG_NEUTRAL,    // Default language
                    SUBLANG_DEFAULT),
        (char*)buffer+22,
        // skip the first 22 bytes because this is the  icon header
        // and directory entry (if the file  contains multiple
        // images, the directory entries will be larger than 22 bytes)
        buffersize-22 // length of buffer
    );

    GROUPICON grData;

    grData.Reserved1 = 0;
    grData.ResourceType = 1;
    grData.ImageCount = 1;

    grData.Width        = 32;                 // icon width (32)
    grData.Height       = 32;                 // icon height (32)
    grData.Colors       = 0;                  // colors (256)
    grData.Reserved2    = 0;                  // reserved, must be 0
    grData.Planes       = 2;                  // color planes
    grData.BitsPerPixel = 32;                 // bit depth
    grData.ImageSize    = buffersize - 22;    // size of image
    grData.ResourceID   = 1;                  // resource ID is 1

    UpdateResource(
        hWhere,
        RT_GROUP_ICON,
        // RT_GROUP_ICON resources contain information about
        // stored icons
        "MAINICON",
        // MAINICON contains information about the application's
        // displayed icon
        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
        &grData,
        // Pointer to this structure
        sizeof(GROUPICON)
    );

    // Perform the update, don't discard changes
    EndUpdateResource(hWhere, FALSE);

    return 0;
}
